package com.gkzf.ai.module.crm.util.packaging;

import com.gkzf.ai.module.crm.controller.admin.creditReport.vo.creditreportdetails.CreditReportDetailsSaveReqVO;
import com.gkzf.ai.module.crm.service.creditReport.CreditReportDetailsService;
import com.gkzf.ai.module.crm.util.YearlyRecord;
import com.gkzf.ai.module.system.api.dict.dto.DictDataRespDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

import static com.gkzf.ai.module.crm.util.AnalysisJsonObjectUtils.*;

/**
 * 计算逾期记录
 */
@Slf4j
public class CalculationOverdueRecord {


    private List<DictDataRespDTO> creditReportOverdueList;

    private String REPORT_PRINT_TIME;

    private String REPORT_TIME;

    private CreditReportDetailsService creditReportDetailsService;

    private Map<String,String> queryLimitMaxCount ;

    /**
     * 解析时间格式
     */
    public static final String YYYY_M_D = "yyyy.m.d";

    public static final String YYYY_MM_DD = "yyyy.MM.dd";

    public CalculationOverdueRecord(List<DictDataRespDTO> creditReportOverdueList,String
                                            REPORT_PRINT_TIME,
                                    String REPORT_TIME,
                                    Map<String,String> queryLimitMaxCount,
                                    CreditReportDetailsService creditReportDetailsService){
        this.creditReportOverdueList = creditReportOverdueList;
        this.REPORT_PRINT_TIME = REPORT_PRINT_TIME;
        this.REPORT_TIME = REPORT_TIME;
        this.queryLimitMaxCount = queryLimitMaxCount;
        this.creditReportDetailsService = creditReportDetailsService;
    }

    /**
     * 解析负债/逾期情况json
     * @param reportQueryMap
     * @param detailsDO
     * @param isShirato 累加是否白户 没有贷款信息就等于默认0
     * @return
     */
    public void getCreditReportLiabilityJson(Map<String,Object> reportQueryMap, CreditReportDetailsSaveReqVO detailsDO, AtomicInteger isShirato,
                                             Map<String,Integer> mechanismNumberMap){


        for (Map.Entry<String, Object> entry : reportQueryMap.entrySet()) {
            if (Objects.equals(entry.getKey(),"贷款") || Objects.equals(entry.getKey(),"贷记卡账户")) {
                Object value = entry.getValue();
                if (value instanceof List annountList) {
                    List<Map<String,Object>> annountMapList = (List<Map<String,Object>>)annountList;
                    for (Map jsonObjectNext : annountMapList) {
                            // 征信报告详情计算
                            creditReportDetailsService.getBasicInfoDebt(jsonObjectNext, entry.getKey(), detailsDO, mechanismNumberMap);
                            // 逾期记录计算
                            getCreditReportOverdue(jsonObjectNext, isShirato);

                    }
                }
            }

        }
    }
    /**
     * 解析逾期贷款数据
     * @param parenMap  账户Map数据
     * @param isShirato 计算是否白户
     * @return
     */
    private void getCreditReportOverdue(Map<String, Object> parenMap,AtomicInteger isShirato){
        creditReportOverdueList.forEach(item ->{
                // 获取管理机构字段
                String governingBodyStr = (String) parenMap.get(GOVERNING_BODY);
                String type;
                // 1.判断是否出现银行字符 出现则 return
                if (!StringUtils.isNotBlank(governingBodyStr)){
                    type = COMMA+CREDITCARD;
                }else {
                    type = COMMA+LOANS;
                }

                Map<String,YearlyRecord> repaymentRecord = (Map<String,YearlyRecord>)parenMap.get(OVERDUE_REPAYMENT_RECORD);
                /*
                 小白户：所有账户状态明细（信贷交易信息明细：非循环贷账户、循环贷账户一、循环贷账户二、贷记卡账户、准贷记卡账户），
                 还款记录表-年份中对应第一行中出现的字段<6；或近两年内无账户明细（以到期日期为准），以征信报告打印日期为准，往前倒推时间
                 */
                // 等于小白户1 或者 等于初始值时继续计算  出计算出等于0时  则有一不满足则就不是小白户
                if (isShirato.get() == 1 || isShirato.get() == 99) {
                    String expirationTime = (String)parenMap.get(EXPIRATION_TIME);
                    int isXiaoBaiHu = getXiaoBaiHu(repaymentRecord,expirationTime,REPORT_PRINT_TIME);
                    isShirato.set(isXiaoBaiHu);
                }
                // 将单个账户所有还价记录按照时间顺序组成一个集合 根据 1 6 12 24 60的长度进行计算
                // 在将单个账户数据保存 循环多账户累加 计算结果
                List<YearlyRecord> yearlyRecordList = getAnalysisJson(repaymentRecord,REPORT_TIME,new AtomicBoolean(true));
                if (yearlyRecordList.isEmpty()) {
                    /*
                     判断 当这些key 有值时 不需要填默认值
                     */
                    if (Objects.isNull(queryLimitMaxCount.get(item.getValue() +OVERDUE_REPAYMENT_NUMBER+type))){
                        queryLimitMaxCount.put(item.getValue() +OVERDUE_REPAYMENT_NUMBER+type, "0");
                    }
                    if (Objects.isNull(queryLimitMaxCount.get(item.getValue() +OVERDUE_REPAYMENT_CONTINUOUS_NUMBER+type))){
                        queryLimitMaxCount.put(item.getValue() + OVERDUE_REPAYMENT_CONTINUOUS_NUMBER+type,  "0");
                    }
                    if (Objects.isNull(queryLimitMaxCount.get(item.getValue() +OVERDUE_REPAYMENT_MAX_NUMBER+type))){
                        queryLimitMaxCount.put(item.getValue() + OVERDUE_REPAYMENT_MAX_NUMBER+type, "0");
                    }
                    if (Objects.isNull(queryLimitMaxCount.get(item.getValue() +OVERDUE_REPAYMENT_MAX_MONEY+type))){
                        queryLimitMaxCount.put(item.getValue() + OVERDUE_REPAYMENT_MAX_MONEY+type,"0");
                    }
                    return;
                }

                //总逾期次数 一个月 1次  6个月 6次 12个月 12次 24个月 24次 60个月  60次
                try {
                    List<Map<String, String>> analysisJson = jsonToList(yearlyRecordList);
                    // 判断担保人代还和以资抵债
                    if(Objects.equals(type, COMMA+LOANS)){
                        /*
                         不存在对于key值 或者 对应value 等于 0时进行对比
                         */
                        if (!queryLimitMaxCount.containsKey(GUARANTOR_REPAYMENT) || Objects.equals(queryLimitMaxCount.get(GUARANTOR_REPAYMENT),"0")){
                            int guarantorRepayment = getGuarantorRepayment(analysisJson);
                            queryLimitMaxCount.put(GUARANTOR_REPAYMENT, String.valueOf(guarantorRepayment));
                        }
                        if (!queryLimitMaxCount.containsKey(SETTLE_DEBTS_WITH_CAPITAL) || Objects.equals(queryLimitMaxCount.get(SETTLE_DEBTS_WITH_CAPITAL),"0")){
                            int settleDebtsWithCapital = getSettleDebtsWithCapital(analysisJson);
                            queryLimitMaxCount.put(SETTLE_DEBTS_WITH_CAPITAL, String.valueOf(settleDebtsWithCapital));
                        }


                    }
                    // 判断长度 如何材料提供的还款记录数量不够 设置的60个月则 还价记录有多少就设置成多少避免越界
                    int monthValue = Math.min(Integer.parseInt(item.getValue()), analysisJson.size());
                    Integer sumLengthOfNumber = findSumLengthOfNumber(analysisJson, monthValue);
                    String defaultsumLengthOfNumber = queryLimitMaxCount.get(item.getValue() + OVERDUE_REPAYMENT_NUMBER + type);
                    Integer overdueMaxLengNumber = StringUtils.isNotBlank(defaultsumLengthOfNumber)? Integer.valueOf(defaultsumLengthOfNumber) :0;
                    // 这个是累加次数不是取最大和下面3个判断不一样
                    setCreditReportOverdue(sumLengthOfNumber+overdueMaxLengNumber, item.getValue(), OVERDUE_REPAYMENT_NUMBER, type);

                    //连续逾期次数一个月  6个月 12个月  24个月  60个月
                    int maxLengthOfConsecutiveNumbers = findMaxLengthOfConsecutiveNumbers(analysisJson, monthValue);
                    setCreditReportOverdue(maxLengthOfConsecutiveNumbers,item.getValue(),OVERDUE_REPAYMENT_CONTINUOUS_NUMBER,type);

                    //最大逾期月数一个月  6个月 12个月  24个月  60个月
                    int maxLengthOfMonth = findMaxLengthOfMonth(analysisJson, monthValue);
                    setCreditReportOverdue(maxLengthOfMonth,item.getValue(),OVERDUE_REPAYMENT_MAX_NUMBER,type);

                    //最大逾期金额一个月  6个月 12个月  24个月  60个月
                    BigDecimal maxLengthOfMoney = findMaxLengthOfMoney(analysisJson, monthValue);
                    setCreditReportOverdue(maxLengthOfMoney,item.getValue(),OVERDUE_REPAYMENT_MAX_MONEY,type);

                }
                // 捕捉越界异常
                catch (IndexOutOfBoundsException e){
                    e.printStackTrace();
                }


        });
    }


    /**
     * 计算
     * 最大逾期金额一个月  6个月 12个月  24个月  60个月
     * 最大逾期月数一个月  6个月 12个月  24个月  60个月
     * 连续逾期次数一个月  6个月 12个月  24个月  60个月
     * @param computationResult 计算得出的值
     * @param itemValue 1，,6，,12，,34，,60的字典对于值
     * @param overdueRepaymentType 区分 金额 月数 次数的类型字符串
     * @param type 区分贷款还是信用卡的类型
     */
    private void setCreditReportOverdue(Object computationResult,String itemValue, String overdueRepaymentType, String type){
        //最大逾期金额一个月  6个月 12个月  24个月  60个月
        //最大逾期月数一个月  6个月 12个月  24个月  60个月
        //连续逾期次数一个月  6个月 12个月  24个月  60个月
        String defaultMaxLengthOfMonthValue = queryLimitMaxCount.get(itemValue + overdueRepaymentType + type);
        String overdueNumber = StringUtils.isNotBlank(defaultMaxLengthOfMonthValue)?defaultMaxLengthOfMonthValue:"0";
        // 如果最大逾期月数大于最大值 或者 最大逾期月数为空 则不进行判断
        if (computationResult instanceof Integer integer && Integer.parseInt(overdueNumber) > integer){
            queryLimitMaxCount.put(itemValue + overdueRepaymentType+type, overdueNumber);
        }
        else if (computationResult instanceof BigDecimal bigDecimal && new BigDecimal(overdueNumber).compareTo(bigDecimal) > 0){
            queryLimitMaxCount.put(itemValue + overdueRepaymentType+type, overdueNumber);
        }
        // 如果最大逾期月数小于最大值 则进行判断
        else {
            queryLimitMaxCount.put(itemValue + overdueRepaymentType+type, String.valueOf(computationResult));
        }
    }


    /**
     * 获取小白户
     * @return
     */
    public static int getXiaoBaiHu(Map<String,YearlyRecord> repaymentRecordMap, String expirationTime,String reportTime){
        //还款记录表-年份中对应第一行中出现的字段<6 累计年份
        AtomicInteger monthNumber = new AtomicInteger();
        repaymentRecordMap.entrySet().forEach(item ->{
            item.getValue().getMonthList().forEach(yearlyRecord -> {
                if (StringUtils.isNotBlank(yearlyRecord)) {
                    monthNumber.incrementAndGet();
                }
            });

        });
        if (monthNumber.get() < 6){
            return 1;
        }
        // 或近两年内无账户明细（以到期日期为准）
        if (StringUtils.isNotBlank(expirationTime)){
            LocalDate ExpirationTimeDate = null;
            try {
                ExpirationTimeDate = convertDate(expirationTime);
            }catch (DateTimeParseException e){
                return 0;
            }
            LocalDate reportTimeDate = convertDate(reportTime );
            if (reportTimeDate.minusYears(2).isAfter(ExpirationTimeDate)){
                return 1;
            }
        }
        return 0;
    }

    public static LocalDate convertDate(String dateStr){

        try {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern(YYYY_MM_DD);
            return LocalDate.parse(dateStr, formatter);
        } catch (DateTimeParseException e) {
            log.info("征信报告打印日期格式不正确: {}", e.getMessage());
            throw new DateTimeParseException("征信报告打印日期格式不正确", dateStr, 0);
        }
    }

}
